home *** CD-ROM | disk | FTP | other *** search
/ InterCD 2000 September / september_2000.iso / intercd / root / ^Linux / WindowMaker / src / xdnd.c < prev    next >
Encoding:
C/C++ Source or Header  |  1999-10-16  |  10.1 KB  |  336 lines

  1. /* Many part of code are ripped of an example from JX's site */
  2.  
  3. #include "wconfig.h"
  4.  
  5. #ifdef XDND
  6.  
  7. #include <X11/Xlib.h>
  8. #include "WindowMaker.h"
  9. #include "window.h"
  10. #include "dock.h"
  11. #include "xdnd.h"
  12. #include "motif.h"
  13.  
  14. #include "workspace.h"
  15.  
  16. #include "stdlib.h"
  17.  
  18. #include <X11/Xatom.h>
  19.  
  20.  
  21. #define XDND_VERSION 3L
  22.  
  23. Atom _XA_XdndAware;
  24. Atom _XA_XdndEnter;
  25. Atom _XA_XdndLeave;
  26. Atom _XA_XdndDrop;
  27. Atom _XA_XdndPosition;
  28. Atom _XA_XdndStatus;
  29. Atom _XA_XdndActionCopy;
  30. Atom _XA_XdndSelection;
  31. Atom _XA_XdndFinished;
  32. Atom _XA_WINDOWMAKER_XDNDEXCHANGE;
  33.  
  34. /*
  35. Atom _XA_MOTIF_DRAG_RECEIVER_INFO;
  36. Atom _XA_MOTIF_DRAG_AND_DROP_MESSAGE;
  37. */
  38.  
  39. Atom atom_support;
  40.  
  41. void wXDNDInitializeAtoms()
  42. {
  43.  
  44.     _XA_XdndAware = XInternAtom(dpy, "XdndAware", False);
  45.     _XA_XdndEnter = XInternAtom(dpy, "XdndEnter", False);
  46.     _XA_XdndLeave = XInternAtom(dpy, "XdndLeave", False);
  47.     _XA_XdndDrop = XInternAtom(dpy, "XdndDrop", False);
  48.     _XA_XdndPosition = XInternAtom(dpy, "XdndPosition", False);
  49.     _XA_XdndStatus = XInternAtom(dpy, "XdndStatus", False);
  50.     _XA_XdndActionCopy = XInternAtom(dpy, "XdndActionCopy", False);
  51.     _XA_XdndSelection = XInternAtom(dpy, "XdndSelection", False);
  52.     _XA_XdndFinished = XInternAtom(dpy, "XdndFinished", False);
  53.  
  54.     _XA_WINDOWMAKER_XDNDEXCHANGE = XInternAtom(dpy, "_WINDOWMAKER_XDNDEXCHANGE", False);
  55.  
  56.     /*
  57.     _XA_MOTIF_DRAG_RECEIVER_INFO = XInternAtom(dpy, "_MOTIF_DRAG_RECEIVER_INFO",False);
  58.     _XA_MOTIF_DRAG_AND_DROP_MESSAGE = XInternAtom(dpy, "_MOTIF_DRAG_AND_DROP_MESSAGE", False);
  59.     */
  60. }
  61.  
  62. void wXDNDMakeAwareness(Window window) {
  63.     long int xdnd_version = 3;
  64.     /*
  65.     MotifDragReceiverInfo info;
  66.     */
  67.     XChangeProperty (dpy, window, _XA_XdndAware, XA_ATOM,
  68.             32, PropModeAppend, (char *)&xdnd_version, 1);
  69.  
  70.     /*** MOTIF ***
  71.     info.byte_order = '\0';
  72.     info.protocol_version = 0;
  73.     info.protocol_style = XmDRAG_DYNAMIC;
  74.     info.proxy_window = 0;
  75.     info.num_drop_sites = 0;
  76.     info.total_size = sizeof(info);
  77.  
  78.     XChangeProperty (dpy, window,
  79.                    _XA_MOTIF_DRAG_RECEIVER_INFO,
  80.                    _XA_MOTIF_DRAG_RECEIVER_INFO,
  81.                    8, PropModeReplace,
  82.                    (unsigned char *)&info,
  83.                    sizeof (info));
  84.                    */
  85. }
  86.  
  87. void wXDNDClearAwareness(Window window) {
  88.     long int xdnd_version = 3;
  89.     XDeleteProperty (dpy, window, _XA_XdndAware);
  90. }
  91.  
  92. Bool
  93. wXDNDProcessSelection(XEvent *event)
  94. {
  95.     WScreen *scr = wScreenForWindow(event->xselection.requestor);
  96.     char *dropdata;
  97.     char *retain;
  98.     Atom ret_type;
  99.     int ret_format;
  100.     unsigned long ret_item;
  101.     unsigned long remain_byte;
  102.     char * delme;
  103.     XEvent xevent;
  104.     Window selowner = XGetSelectionOwner(dpy,_XA_XdndSelection);
  105.     WMBag *items;
  106.  
  107.  
  108.     XGetWindowProperty(dpy, event->xselection.requestor,
  109.             _XA_WINDOWMAKER_XDNDEXCHANGE,
  110.             0, 65536, True, atom_support, &ret_type, &ret_format,
  111.             &ret_item, &remain_byte, (unsigned char **)&delme);
  112.     if (delme){
  113.         scr->xdestring=delme;
  114.     }
  115.  
  116.     /*send finished*/
  117.     memset (&xevent, 0, sizeof(xevent));
  118.     xevent.xany.type = ClientMessage;
  119.     xevent.xany.display = dpy;
  120.     xevent.xclient.window = selowner;
  121.     xevent.xclient.message_type = _XA_XdndFinished;
  122.     xevent.xclient.format = 32;
  123.     XDND_FINISHED_TARGET_WIN(&xevent) = event->xselection.requestor;
  124.     XSendEvent(dpy, selowner, 0, 0, &xevent);
  125.  
  126.     /*process dropping*/
  127.     if (scr->xdestring) {
  128.         int length, str_size;
  129.         int total_size = 0;
  130.         char *tmp;
  131.  
  132.         items = WMCreateBag(1);
  133.         retain = wstrdup(scr->xdestring);
  134.         XFree(scr->xdestring); /* since xdestring was created by Xlib */
  135.  
  136.         length = strlen(retain);
  137.  
  138.         /* search in string */
  139.         while (length--) {
  140.             if (retain[length] == '\r') { /* useless char, nuke it */
  141.                 retain[length] = 0;
  142.             }
  143.             if (retain[length] == '\n') {
  144.                 str_size = strlen(&retain[length + 1]);
  145.                 if(str_size) {
  146.                     WMPutInBag(items, wstrdup(&retain[length + 1]));
  147.                     total_size += str_size + 3; /* reserve for " \"\"" */
  148.                     if (length)
  149.                         WMAppendBag(items, WMCreateBag(1));
  150.                 }
  151.                 retain[length] = 0;
  152.             }
  153.         }
  154.         /* final one */
  155.         WMPutInBag(items, wstrdup(retain));
  156.         total_size += strlen(retain) + 3;
  157.         free(retain);
  158.  
  159.         /* now pack new string */
  160.         scr->xdestring = wmalloc(total_size);
  161.         scr->xdestring[0]=0; /* empty string */
  162.         for(length = WMGetBagItemCount(items)-1; length >=0; length--) {
  163.             tmp = WMGetFromBag(items, length);
  164.             if (!strncmp(tmp,"file:",5)) {
  165.                 /* add more 2 chars while removing 5 is harmless */
  166.                 strcat(scr->xdestring, " \"");
  167.                 strcat(scr->xdestring, &tmp[5]);
  168.                 strcat(scr->xdestring, "\"");
  169.             } else {
  170.                 /* unsupport object, still need more " ? tell ]d */
  171.                 strcat(scr->xdestring, &tmp[5]);
  172.             }
  173.             free(tmp);
  174.         }
  175.         WMFreeBag(items);
  176.         wDockReceiveDNDDrop(scr,event);
  177.         /*
  178.         printf("free ");
  179.         puts(scr->xdestring);
  180.         */
  181.         free(scr->xdestring); /* this xdestring is not from Xlib (no XFree) */
  182.     }
  183. }
  184.  
  185. Bool
  186. isAwareXDND(Window window)
  187. {
  188.     Atom actual;
  189.     int format;
  190.     unsigned long count, remaining;
  191.     unsigned char *data=0;
  192.     Atom *types, *t;
  193.  
  194.     if (!window) return False;
  195.     XGetWindowProperty (dpy, window, _XA_XdndAware,
  196.                     0, 0x8000000L, False, XA_ATOM,
  197.                     &actual, &format,
  198.                     &count, &remaining, &data);
  199.     if (actual != XA_ATOM || format != 32 || count == 0 || !data) {
  200.         if (data)
  201.             XFree (data);
  202.         return False;
  203.     }
  204.     if (data)
  205.         XFree (data);
  206.     return True;
  207. }
  208.  
  209. Bool
  210. acceptXDND(Window window)
  211. {
  212.     WScreen *scr = wScreenForWindow(window);
  213.     WWindow *wwin = wWindowFor(window);
  214.     WDock *dock;
  215.     int icon_pos,i;
  216.     
  217.     icon_pos = -1;
  218.     if ((dock = scr->dock)!=NULL) {
  219.         for (i=0; i<dock->max_icons; i++) {
  220.             if (dock->icon_array[i]
  221.                 && dock->icon_array[i]->icon->core->window==window) {
  222.                 icon_pos = i;
  223.                 break;
  224.             }
  225.         }
  226.     }
  227.     if (icon_pos<0 && (dock = scr->workspaces[scr->current_workspace]->clip)!=NULL) {
  228.         for (i=0; i<dock->max_icons; i++) {
  229.             if (dock->icon_array[i]
  230.                 && dock->icon_array[i]->icon->core->window==window) {
  231.                 icon_pos = i;
  232.                 break;
  233.             }
  234.         }
  235.     }
  236.     if (icon_pos<0) return False;
  237.     if (!dock) return False;
  238.     if (isAwareXDND(dock->icon_array[icon_pos]->icon->icon_win)) return False;
  239.     
  240.     if (dock->icon_array[icon_pos]->dnd_command!=NULL) return True;
  241.     
  242.     return False;
  243. }
  244.  
  245. Bool
  246. wXDNDProcessClientMessage(XClientMessageEvent *event)
  247. {
  248.     /* test */
  249.     {
  250.     char * name = XGetAtomName(dpy, event->message_type);
  251.     /*
  252.     printf("Get %s\n",name);
  253.     */
  254.     XFree(name);
  255.     }
  256.  
  257.     /*
  258.     if (event->message_type == _XA_MOTIF_DRAG_AND_DROP_MESSAGE) {
  259.         printf("motif dnd msg %d\n",event->data.b[0]);
  260.         if (event->data.b[0] == XmDROP_START){
  261.             unsigned x_root, y_root, flags;
  262.             unsigned char reason;
  263.             unsigned long timestamp;
  264.             Atom atom;
  265.             Window source_window;
  266.             MotifDragInitiatorInfo *initiator_info;
  267.             Atom ret_type;
  268.             int ret_format;
  269.             unsigned long ret_item;
  270.             unsigned long remain_byte;
  271.  
  272.             reason = event->data.b[0];
  273.             flags = event->data.s[1];
  274.             timestamp = event->data.l[1];
  275.             x_root = event->data.s[4];
  276.             y_root = event->data.s[5];
  277.             atom = event->data.l[3];
  278.             source_window = event->data.l[4];
  279.  
  280.     XGetWindowProperty(dpy, source_window, atom,
  281.             0, sizeof(*initiator_info), True, atom_support,
  282.             &ret_type, &ret_format,
  283.             &ret_item, &remain_byte, (unsigned char **)&initiator_info);
  284.         }
  285.     }
  286.     else */
  287.     if (event->message_type == _XA_XdndEnter) {
  288.         if ((event->data.l[1] & 1) == 0){
  289.             atom_support = event->data.l[2];
  290.         }
  291.         /*
  292.         else puts("enter more than 3 types");
  293.         */
  294.         return True;
  295.     } else if (event->message_type == _XA_XdndLeave) {
  296.         return True;
  297.     } else if (event->message_type == _XA_XdndDrop) {
  298.         if (event->data.l[0] == XGetSelectionOwner(dpy, _XA_XdndSelection)){
  299.             XConvertSelection(dpy, _XA_XdndSelection, atom_support,
  300.                     _XA_WINDOWMAKER_XDNDEXCHANGE, event->window, CurrentTime);
  301.         }
  302.         else {
  303.             puts("wierd selection owner? QT?");
  304.             XConvertSelection(dpy, _XA_XdndSelection, atom_support,
  305.                     _XA_WINDOWMAKER_XDNDEXCHANGE, event->window, CurrentTime);
  306.         }
  307.         return True;
  308.     } else if (event->message_type == _XA_XdndPosition) {
  309.         XEvent xevent;
  310.         Window srcwin = event->data.l[0];
  311.         if (atom_support != XInternAtom(dpy, "text/uri-list", False)) {
  312.             return True;
  313.         }
  314.         {
  315.             memset (&xevent, 0, sizeof(xevent));
  316.             xevent.xany.type = ClientMessage;
  317.             xevent.xany.display = dpy;
  318.             xevent.xclient.window = srcwin;
  319.             xevent.xclient.message_type = _XA_XdndStatus;
  320.             xevent.xclient.format = 32; 
  321.  
  322.             XDND_STATUS_TARGET_WIN (&xevent) = event->window;
  323.             XDND_STATUS_WILL_ACCEPT_SET (&xevent, acceptXDND(event->window));
  324.             XDND_STATUS_WANT_POSITION_SET(&xevent, True);
  325.             XDND_STATUS_RECT_SET(&xevent, 0, 0, 1024,768);
  326.             XDND_STATUS_ACTION(&xevent) = _XA_XdndActionCopy;
  327.  
  328.             XSendEvent(dpy, srcwin, 0, 0, &xevent);
  329.         }
  330.         return True;
  331.     }
  332.     return False;
  333. }
  334.  
  335. #endif
  336.